package io.bhex.app.hardware;

import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Environment;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import io.bhex.app.R;
import io.bhex.baselib.utils.DebugLog;
import io.bhex.baselib.utils.ToastUtils;

/**
 * ================================================
 * 作   者：ppzhao
 * 创建时间：2019-11-14
 * 邮   箱：
 * 描   述：
 * ================================================
 */

public class CameraHardWare {

    private static final String TAG = "CameraHardWare";
    private static CameraHardWare instance;
    private static Context mContext;
    private Camera mCamera;
    private MediaRecorder mMediaRecorder;
    private String outPutFile;

    public static CameraHardWare getInstance(Context context) {
        if (instance == null) {
            instance = new CameraHardWare();
            mContext = context;
        }
        return instance;
    }

    /**
     * 检测相机权限
     *
     * @param context
     * @return
     */
    public boolean checkCameraHardware(Context context) {
        // 支持所有版本
        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
        //  Android 2.3 (API Level 9) 及以上的
        // return  Camera.getNumberOfCameras() > 0;
    }

    /**
     * 获取相机
     * <p>
     * 注意： 在部分设备上，打开摄像头时可能会花费较长的时间，因此此操作应该在子线程上执行，然后以回调的方式传递Camera 对象，避免出现ANR；
     *
     * @return
     */
    public Camera getCameraInstance() {
        Camera c = null;
        try {
            // 在多个摄像头时，默认打开后置摄像头
//            c = Camera.open();
            int numberOfCameras = Camera.getNumberOfCameras();
            if (numberOfCameras > 0) {
                if (numberOfCameras < 2) {
                    c = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
                } else {
                    // Android 2.3（API 9之后可指定cameraId摄像头id，可选值为后置（CAMERA_FACING_BACK）/前置（ CAMERA_FACING_FRONT）
                    c = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
                }
            }

        } catch (Exception e) {
            // Camera被占用或者设备上没有相机时会崩溃。
        }
        return c;  // returns null if camera is unavailable
    }

    public boolean prepareVideoRecorder(Camera camera, CameraPreview cameraPreview, long maxDurationRecord, MediaRecorder.OnInfoListener infoListener) {
        if (camera == null || cameraPreview == null) {
            return false;
        }

        this.mCamera = camera;
        mMediaRecorder = new MediaRecorder();

        // Step 1: Unlock and set camera to MediaRecorder
        this.mCamera.unlock();
        mMediaRecorder.setCamera(this.mCamera);

        // Step 2: Set sources
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

        // Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
//        mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_720P));
        mMediaRecorder.setProfile(getCamcorderProfile());

        //设置录制视频的方向
        mMediaRecorder.setOrientationHint(270);

        // Step 4: Set output file
        outPutFile = getOutputMediaFile(MEDIA_TYPE_VIDEO).toString();
        mMediaRecorder.setOutputFile(outPutFile);

        // Step 5: Set the preview output
        mMediaRecorder.setPreviewDisplay(cameraPreview.getHolder().getSurface());

        // Step 6: Prepare configured MediaRecorder
        mMediaRecorder.setMaxDuration((int) maxDurationRecord);//设置最大录制时长
        mMediaRecorder.setOnInfoListener(infoListener);
        try {
            mMediaRecorder.prepare();
        } catch (IllegalStateException e) {
            DebugLog.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
            releaseMediaRecorder();
            return false;
        } catch (IOException e) {
            DebugLog.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
            releaseMediaRecorder();
            return false;
        }
        return true;
    }

    /**
     *  * @see #QUALITY_LOW
     *      * @see #QUALITY_HIGH
     *      * @see #QUALITY_QCIF
     *      * @see #QUALITY_CIF
     *      * @see #QUALITY_480P
     *      * @see #QUALITY_720P
     *      * @see #QUALITY_1080P
     *      * @see #QUALITY_2160P
     *      * @see #QUALITY_TIME_LAPSE_LOW
     *      * @see #QUALITY_TIME_LAPSE_HIGH
     *      * @see #QUALITY_TIME_LAPSE_QCIF
     *      * @see #QUALITY_TIME_LAPSE_CIF
     *      * @see #QUALITY_TIME_LAPSE_480P
     *      * @see #QUALITY_TIME_LAPSE_720P
     *      * @see #QUALITY_TIME_LAPSE_1080P
     *      * @see #QUALITY_TIME_LAPSE_2160P
     *      * @see #QUALITY_HIGH_SPEED_LOW
     *      * @see #QUALITY_HIGH_SPEED_HIGH
     *      * @see #QUALITY_HIGH_SPEED_480P
     *      * @see #QUALITY_HIGH_SPEED_720P
     *      * @see #QUALITY_HIGH_SPEED_1080P
     *      * @see #QUALITY_HIGH_SPEED_2160P
     *
     * @return
     */
    private CamcorderProfile getCamcorderProfile2() {
        if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_QVGA)) {
            return CamcorderProfile.get(CamcorderProfile.QUALITY_QVGA);
        }else{
            ToastUtils.showShort("No this Profile");
          return CamcorderProfile.get(CamcorderProfile.QUALITY_LOW);
        }
    }

    private CamcorderProfile getCamcorderProfile() {
        if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_QVGA)) {
            return CamcorderProfile.get(CamcorderProfile.QUALITY_QVGA);
        }else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_CIF)) {
            return CamcorderProfile.get(CamcorderProfile.QUALITY_CIF);
        }else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_480P)) {
            return CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
        }else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_720P)) {
            return CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
        } else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_HIGH)) {
            return CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
        } else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_LOW)) {
            return CamcorderProfile.get(CamcorderProfile.QUALITY_LOW);
        }else{

         return CamcorderProfile.get(CamcorderProfile.QUALITY_LOW);
        }
    }

    public void releaseMediaRecorder() {
        if (mMediaRecorder != null) {
            mMediaRecorder.reset();   // clear recorder configuration
            mMediaRecorder.release(); // release the recorder object
            mMediaRecorder = null;
            mCamera.lock();           // lock camera for later use
        }
    }

    public void releaseCamera() {
        if (mCamera != null) {
            mCamera.release();        // release the camera for other applications
            mCamera = null;
        }
    }

    public static final int MEDIA_TYPE_IMAGE = 1;
    public static final int MEDIA_TYPE_VIDEO = 2;

    /**
     * Create a file Uri for saving an image or video
     */
    private static Uri getOutputMediaFileUri(int type) {
        return Uri.fromFile(getOutputMediaFile(type));
    }

    /**
     * Create a File for saving an image or video
     */
    private static File getOutputMediaFile(int type) {
        // To be safe, you should check that the SDCard is mounted
        // using Environment.getExternalStorageState() before doing this.
        String fileDirName = mContext.getString(R.string.app_name);
        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES), fileDirName);
        // This location works best if you want the created images to be shared
        // between applications and persist after your app has been uninstalled.

        // Create the storage directory if it does not exist
        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdirs()) {
                DebugLog.d(fileDirName, "failed to create directory");
                return null;
            }
        }

        // Create a media file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        File mediaFile;
        if (type == MEDIA_TYPE_IMAGE) {
            mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                    "IMG_" + timeStamp + ".jpg");
        } else if (type == MEDIA_TYPE_VIDEO) {
            mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                    "VID_" + timeStamp + ".mp4");
        } else {
            return null;
        }

        return mediaFile;
    }

    public void stopMediaRecorder() {
        // stop recording and release camera
        if (mMediaRecorder != null) {
            mMediaRecorder.stop();  // stop the recording
        }
    }

    public void startMediaRecorder() {
        // Camera is available and unlocked, MediaRecorder is prepared,
        // now you can start recording
        if (mMediaRecorder != null) {
            mMediaRecorder.start();
        }
    }

    public void lockCamera() {
        if (mCamera != null) {
            mCamera.lock();         // take camera access back from MediaRecorder
        }
    }

    public String getVideoFile() {
        return outPutFile;
    }
}
